{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import wave\n",
    "import numpy as np\n",
    "import pylab as plt\n",
    "from scipy.signal import firwin\n",
    "from scipy.signal.signaltools import get_window\n",
    "from utils import *\n",
    "%matplotlib inline\n",
    "np.set_printoptions(precision=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "PHASE = 8\n",
    "TAPS = 32\n",
    "taps = firwin(TAPS*PHASE, 1/(PHASE), window=\"blackman\")\n",
    "# scaling\n",
    "taps = taps * PHASE\n",
    "\n",
    "c = []\n",
    "for i in range(PHASE):\n",
    "    c += get_c(TAPS, i/PHASE).tolist()\n",
    "\n",
    "taps = np.array(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "out_sample = 0\n",
    "sample_inc = 1.001"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "fname = \"sine.wav\"\n",
    "f = wave.open(fname, 'rb')\n",
    "\n",
    "f_out = wave.open(\"wave_out.wav\", \"wb\")\n",
    "f_out.setframerate(48000)\n",
    "f_out.setsampwidth(3)\n",
    "f_out.setnchannels(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "audio_delay_line = np.zeros(TAPS)\n",
    "delay_line_sample = -TAPS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def sample_to_int(data):\n",
    "        d = int.from_bytes(data, byteorder='little', signed=True)\n",
    "        return d\n",
    "\n",
    "def int_to_sample(data):\n",
    "        d = int(data)\n",
    "        return d.to_bytes(3, byteorder='little', signed=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# bank selection\n",
    "def c(p):\n",
    "    i_p = p\n",
    "    i = [x+p*TAPS for x in range(TAPS)]\n",
    "    return taps[i]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def calc_fir(data, phase):\n",
    "    return np.sum(audio_delay_line*np.array(get_c(TAPS, phase, 1.0)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def process_sample(data):\n",
    "    global delay_line_sample\n",
    "    global out_sample\n",
    "    global audio_delay_line\n",
    "    audio_delay_line = np.roll(audio_delay_line, 1)\n",
    "    audio_delay_line[0] = data\n",
    "    delay_line_sample += 1\n",
    "    while(out_sample < delay_line_sample):\n",
    "        rem = out_sample % 1\n",
    "        ret = calc_fir(data, rem)\n",
    "        f_out.writeframes(int_to_sample(ret))\n",
    "        out_sample += sample_inc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "while(True):\n",
    "    data = f.readframes(1)\n",
    "    if(len(data)==0):\n",
    "        break\n",
    "    process_sample(sample_to_int(data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "f.close()\n",
    "f_out.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
